﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataEntites;

namespace NoSQLDataProvider
{
    public class NoSQLBaseRepository<T> where T : Entity
    {
        #region Get method

        public virtual T Get(Func<T, bool> condition)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().FirstOrDefault(condition);
            }
        }

        public virtual List<TResult> Get<TResult>(Func<T, TResult> selector)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().Select(selector).ToList();
            }
        }

        public virtual List<TResult> Get<TResult>(Func<T, TResult> selector, Func<T, bool> condition)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().Where(condition).Select(selector).ToList();
            }
        }

        public virtual List<T> GetAll(Func<T, bool> condition)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().Where(condition).ToList();
            }
        }

        public virtual List<T> GetAll(Func<T, bool> condition, int start, int take)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().Where(condition).Skip(start).Take(take).ToList();
            }
        }

        #endregion

        #region Add method

        public virtual T Add(T entity)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                db.Provider.GetCollection<T>().Insert(new List<T> {entity});
                return entity;
            }
        }

        public virtual List<T> Add(List<T> entities)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                db.Provider.GetCollection<T>().Insert(entities);
                return entities;
            }
        }

        #endregion

        #region Update method

        public virtual T Update(Func<T, bool> condition, T newEntity)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                //var tEntity = db.Provider.GetCollection<T>().First(condition);
                db.Provider.GetCollection<T>().Save(newEntity);
                //db.SubmitChanges();
                return newEntity;
            }
        }

        public virtual T Update(Func<T, bool> condition, T newEntity, string[] includeProperties)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                //var tEntity = db.Provider.GetCollection<T>().First(condition);
                db.Provider.GetCollection<T>().Save(newEntity);
                //db.SubmitChanges();
                return newEntity;
            }
        }

        public virtual T Update(Func<T, bool> condition, Dictionary<string, object> updateField)
        {
            throw new Exception("Not implemented");
        }

        public virtual List<T> Update(Func<T, bool> condition, Action<IEnumerable<T>> howToUpdateEntity)
        {
            throw new Exception("Not implemented");
        }

        public virtual T Update(Func<T, bool> condition, Action<T> howToUpdateEntity)
        {
            throw new Exception("Not implemented");
        }

        public virtual List<T> UpdateAll(Func<T, bool> condition, Action<T> howToUpdateEntity)
        {
            throw new Exception("Not implemented");
        }

        #endregion

        #region Delete method

        public virtual bool Delete(Func<T, bool> condition)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                try
                {
                    var entity = db.Provider.GetCollection<T>().AsQueryable().Where(condition);
                    if (entity != null)
                    {
                        db.Provider.GetCollection<T>().Delete(entity);
                        return true;
                    }
                    return false;
                }
                catch (Exception error)
                {
                    throw new Exception(error.Message);
                }
            }
        }

        public virtual bool Delete(Func<T, bool> condition, Func<T, int> keys, string primaryKey)
        {
            throw new Exception("Not implemented");
        }

        #endregion

        public virtual int Count(Func<T, bool> condition)
        {
            using (var db = new NoSQLRepositoryContext())
            {
                return db.Provider.GetCollection<T>().AsQueryable().Count(condition);
            }
        }
    }
}
